/*
 * types.js
 *
 * Copyright (C) 2012 - OS3 srl - http://www.os3.it
 *
 * Written by: Fabio Rotondo - fabio.rotondo@os3.it
 *
 * This is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation;
 * version 2 of the License ONLY.
 *
 * This software is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public
 * License along with this software; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 * NOTE: this is the GPL version of the library. If you want to include this 
 *       library inside a CLOSED SOURCE / PROPRIETARY software, you need 
 *       to purchase a COMMERCIAL LICENSE. See http://www.os3.it/license/
 *       for more info.
 */

if ( typeof ( exports ) !== 'undefined' )
{
	var liwe = require ( "./liwe" );
}

liwe.types = {};
liwe.types.dict = function ( obj )
{
	if ( ! obj ) obj = {};

	liwe.types.to_dict ( obj );

	return obj;
};

liwe.types._recur = function ( obj, recur, cback )
{
	if ( ! obj ) return;

	if ( typeof ( recur ) == 'undefined' )
		recur = 1;

	if ( recur == -1 || recur > 1 )
	{
		for ( k in obj )
			if ( typeof ( obj [ k ] ) == 'object' )
				cback ( obj [ k ], ( recur == -1 ? -1 : recur - 1 ) );
	}
};

liwe.types.to_dict = function ( obj, recur )
{
	if ( ! obj ) return null;

	liwe.types._recur ( obj, recur, liwe.types.to_dict );

	liwe.types._iterate ( obj );
	liwe.types._keys ( obj );
	liwe.types._values ( obj );
	liwe.types._count ( obj );
	liwe.types._get ( obj );
	liwe.types._get_name ( obj );
	liwe.types._inherits ( obj );
	liwe.types._clone ( obj );
	liwe.types._to_object ( obj );

	return obj;
};

liwe.types.list = function ( lst )
{
	if ( ! lst ) lst = [];

	liwe.types.to_list ( lst );

	return lst;
};

liwe.types.to_list = function ( lst, recur )
{
	if ( ! lst ) return null;

	liwe.types._recur ( lst, recur, liwe.types.to_list );

	liwe.types._iterate ( lst );
	liwe.types._count ( lst );
	liwe.types._find ( lst );
	liwe.types._list_del ( lst );
	liwe.types._list_insert ( lst );
	liwe.types._list_clear ( lst );

	return lst;
};

// {{{ iterate ( cback ( v, k ) )
liwe.types._iterate = function ( obj )
{
	obj.iterate = function ( cback )
	{
		var k;

		for ( k in obj )
		{
			if ( typeof ( obj [ k ] ) == 'function' ) continue;
			cback ( obj [ k ], k );
		}
	};
};
// }}}
// {{{ count ()
liwe.types._count = function ( obj )
{
	obj.count = function ()
	{
		var k;
		var res = 0;
		
		for ( k in obj )
		{
			if ( ( typeof ( obj [ k ] ) == 'function' ) ) continue;
			res ++;
		}

		return res;
	};
};
// }}}

// dict () methods
// {{{ keys ()
liwe.types._keys = function ( obj )
{

	obj.keys = function ()
	{
		var res = [];

		obj.iterate ( function ( v, k ) { res.push ( k ); } );

		return res;
	};
};
// }}}
// {{{ values ()
liwe.types._values = function ( obj )
{
	obj.values = function ()
	{
		var res = [];

		obj.iterate ( function ( v ) { res.push ( v ); } );

		return res;
	};
};
// }}}
// {{{ get ( key_name, def_val )
liwe.types._get = function ( obj )
{
	obj.get = function ( name, def_val )
	{
		var res = obj [ name ];

		if ( typeof ( res ) == 'undefined' ) return def_val;

		return res;
	};
};
// }}}
// {{{ getName ()
liwe.types._get_name = function ( obj )
{
	obj.getName = function ()
	{
		if ( obj.name ) return obj.name;

		var s = "" + obj;
		var v = s.match ( /^function  *([_a-zA-Z$][_a-zA-Z0-9$]*)  *.*/ ); //new RegExp ( "^function  *(.*) *\(" ) )

		if ( ! v ) return '';

		return v [ 1 ];
	};
};
// }}}
// {{{ inherits ( parent, full )
liwe.types._inherits = function ( obj )
{
	obj.inherits = function ( p, full )
	{
		var name;

		obj.parent = p;
		for ( name in p )
		{
			if ( full || typeof obj [ name ] == 'undefined' ) obj [ name ] = p [ name ];
		}
	};
};
// }}}
// {{{ clone ()
liwe.types._clone = function ( obj )
{
	obj.clone = function ()
	{
		var res ={};
		var name;

		for ( name in obj ) res [ name ] = obj [ name ];

		return res;
	};
};
// }}}

liwe.types._to_object = function ( obj )
{
	obj.to_object = function ()
	{
		var values = {};
		var ks = obj.keys();

		for ( i=0; i < ks.length; i++ )
		{
			var key = ks [ i ];
			values [ key ] = obj [ key ];
		};

		return values;
	};
};

// list () methods
// {{{ find ( key, case_sens, include_func )
liwe.types._find = function ( lst )
{
	lst.find = function ( key, case_sens, include_funcs )
	{
		var k;
		var c = 0;

		if ( ! case_sens ) key = key.toLowerCase ();

		for ( k in lst )
		{
			if ( ( typeof ( lst [ k ] ) == 'function' ) && ( ! include_funcs ) ) continue;

			k = lst [ k ];
			if ( ! case_sens ) k = k.toLowerCase ();
			if ( k == key ) return c;
				
			c++;
		}

		return -1;
	};
};
// }}}
// {{{ del ( pos, how_many )
liwe.types._list_del = function ( lst )
{
	lst.del = function ( pos, how_many )
	{
		if ( ! how_many ) how_many = 1;

		lst.splice ( pos, how_many );
	};
};
// }}}
// {{{ insert ( pos, item )
liwe.types._list_insert = function ( lst )
{
	lst.insert = function ( pos, item )
	{
  		lst.splice ( pos, 0, item );
	};
};
// }}}
// {{{ clear ()
liwe.types._list_clear = function ( lst )
{
	lst.clear = function ()
	{
		lst.length = 0;
	};
};
// }}}

var dict = liwe.types.dict;
var list = liwe.types.list;
var to_dict = liwe.types.to_dict;
var to_list = liwe.types.to_list;

if ( typeof ( exports ) !== 'undefined' ) module.exports = liwe.types;
